#include "Parser.hpp"

libParser::libParser()
{
}

libParser::~libParser()
{
}

int libParser::InitParser()
{
    if (!pbuffer.src_buffer)
    {
        return -1;
    }

    // 前置参数检测完成 启动模块
    Init();
    return 0;
}

int libParser::Init()
{
    thread t_parser(Thread_Parser2, this);
    t_parser.detach();
    b_thread_flag = true;
    WriteLog("Parser begin! INDEX_627");
    return 0;
}

void libParser::Thread_Parser2(void * p_this)
{
    libParser *l = (libParser*)p_this;
    return l->Thread_Parserr2();
}

void libParser::Thread_Parserr2()
{
    int ret;

    while (true)
    {
        //if (!pbuffer.src_array_index_b)
        //{
        //    Sleep(100); //
        //    continue;
        //}
        ParserPack2 pp_local;
        ret = MixPicture(pbuffer.src_array, sample_picture_num);
        if (ret < 0)
        {
            WriteLog("Failed MixPicture. INDEX_811");
            continue;
        }
        ret = RecognitionPicture(src_blend, pp_local.rec);
        if (ret < 0)
        {
            WriteLog("Failed DetectionPicture_GetRect. INDEX_812");
            continue;
        }
        ret = AdjustDuration(pp_local);
        if (ret < 0)
        {
            WriteLog("Failed AdjustDuration. INDEX_813");
            continue;
        }
        ret = PP.AddPP(pp_local);
        if (ret < 0)
        {
            WriteLog("Failed PP.AddPP. INDEX_814");
            continue;
        }
    }
    b_thread_flag = false;
}

int libParser::MixPicture(Mat * _src_array, uint _number)
{
    int ret{ 0 };
    pbuffer.src_buffer_m.lock();
    for (int i = (_number / 2); i > 0; i /= 2) //4 2 1
    {
        ret = AddWeighted_Mat(_src_array, _src_array, i); //这里再试着看怎么改改减少计算量
        if (ret<0)
        {
            break;
        }
    }
    src_blend = _src_array[0].clone();
    for (int i = 0; i < sample_picture_num; i++)
    {
        src_blend_index[i] = pbuffer.src_index[i];
    }
//    _src_array[0].copyTo(src_blend);
    pbuffer.src_buffer_m.unlock();
    return ret;
}

int libParser::AddWeighted_Mat(Mat * _src, Mat * _dst, int num)
{
    if (num < 1)
    {
        return -1;
    }
    for (int i = 0; i < num; i++)
    {
        cv::addWeighted(_src[0 + i * 2], 0.5, _src[1 + i * 2], 0.5, 0.0, _dst[i]);
    }
    return 0;
}

int libParser::RecognitionPicture(Mat _src, vector<Rect>& _rec)
{
    int ret{ 0 };
    if (NULL == _src.data)
    {
        WriteLog("src.date is null! INDEX_815");
        return -1;
    }

    //    Mat src_local = _src.clone(); //换方式 目前还是设置检测区与非检测区
    Mat src_local = _src(PI.rec_pi).clone();
//    Test_Show("src_local", src_local);

    Rect ccomp;
    ret = floodFill(src_local, Point(50, 300), Scalar(111, 111, 111), &ccomp, Scalar(20, 20, 20), Scalar(20, 20, 20));
    if (!ret)
    {
        WriteLog("Failed floodFill. INDEX_816");
        return -1;
    }
//    Test_Show("floodfill", src_local);

    Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
    morphologyEx(src_local, src_local, MORPH_OPEN, element); //
//    Test_Show("morphologyEx", src_local);

    //GaussianBlur(src_local, src_local, Size(3, 3), 0, 0);   //Test_Showmat("Gaussian", src_local, 0.3);  //blur能解决的，不一定非要用上位函数
    //cvtColor 转换从左新生成并传递给右值，原左值内存到此不变？
    cvtColor(src_local, src_local, cv::COLOR_BGR2GRAY);// CV_BGR2GRAY（2.x版本）  COLOR_BGR2GRAY（3.x版本） 反正enum中都是6  可通用 注意命名空间就好

    Canny(src_local, src_local, 3, 100, 3);
//    Test_Show("Canny", src_local);

    vector<vector<Point>> contourss;
    findContours(src_local, contourss, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);

    //去除冗余
    int pmax = (PI.max_rect_width + PI.max_rect_height) * 2;
    int pmin = (PI.max_rect_width + PI.max_rect_height) / 2;//max好确定，min就不好想了，如果只找到指纹的某一块图块，那就很不好弄了
    for (int j{ 0 }; j < contourss.size(); j++)
    {
        if (((contourss.begin() + j)->size() < pmin) || ((contourss.begin() + j)->size() > pmax))
        {
            contourss.erase(contourss.begin() + j);
            j--;
        }
    }
    //////////////////////////////////////////////////////////////////////////建立一个新的总框架
    ret = StatisticsContour(contourss, _rec);
    if (ret < 0)
    {
        WriteLog("Failed StatisticsContour. INDEX_817");
        return -1;
    }

    ret = CheckPixel(_src, _rec);
    if (ret < 0)
    {
        WriteLog("Failed CheckPixel. INDEX_8137");
        return -1;
    }
//    Test_Show("111", _src, _rec);
    return 0;
}

int libParser::StatisticsContour(vector<vector<Point>>& _contour, vector<Rect>& _rec)
{
    if (!_contour.size())
    {
        return -1;
    }
    vector<Rect> c_local;
    //vector<int> i_local;
    //Point average_point;

    for (vector<Point> v_p : _contour)
    {
        Rect re = boundingRect(Mat(v_p)); // minAreaRect 只找最小外接矩形 但这个是需要自己设置矫正的
        if ((re.width >= 20) && (re.width <= PI.max_rect_width) && (re.height >= 15) && (re.height <= PI.max_rect_height))
        {
            c_local.push_back(re);
        }
    }
    for (Rect r : c_local)
    {
        r.y += PI.Caption;
        (_rec).push_back(r);
    }
    return 0;
}

int libParser::CheckPixel(Mat _src, vector<Rect>& _rec)
{
    if (NULL == _src.data)
    {
        WriteLog("src.date is null! INDEX_8157");
        return -1;
    }
    double percent_pix{ 0.0 };
    const double percent_pix_set{ 0.2 }; //数值可能过高了吧···
    int PixRange = 255 / 10; //25

    for (int i = 0; i < _rec.size();)
    {
        int sum_pix{ 0 };
        Mat c_m = _src(_rec[i]).clone();//不一定必须用clone 可只用指针就行
//        Test_Show(i, c_m,Size(c_m.cols*3, c_m.rows * 3),1);
        for (int i = 0; i < c_m.rows; i++)
        {
            for (int j = 0; j < c_m.cols; j++)
            {
                if ((abs(c_m.at<cv::Vec3b>(i, j)[0] - PI.BaseColor1_RGB[2]) < PixRange) &&
                    (abs(c_m.at<cv::Vec3b>(i, j)[1] - PI.BaseColor1_RGB[1]) < PixRange) &&
                    (abs(c_m.at<cv::Vec3b>(i, j)[2] - PI.BaseColor1_RGB[0]) < PixRange)) //注意像素顺序
                {
                    sum_pix++;
                }
            }
        }
        percent_pix = (float)sum_pix / (float)(c_m.rows*c_m.cols); //设置多少就算符合指纹切片```
        if (percent_pix > percent_pix_set)
        {
            i++;
        }
        else
        {
            _rec.erase(_rec.begin() + i);
        }
    }

    return 0;
}

int libParser::AdjustDuration(ParserPack2 & _pp)
{
    _pp.min_index = src_blend_index[0];
    for (int64_t tt : src_blend_index)
    {
        _pp.min_index = (_pp.min_index < tt) ? _pp.min_index : tt;
        _pp.max_index = (_pp.max_index > tt) ? _pp.max_index : tt;
    }
    int64_t half_duration;
    half_duration = (_pp.max_index - _pp.min_index) / 2;
    if (half_duration <= 0)
    {
        return -1;
    }
    _pp.min_index -= half_duration * 3; //这里微调一下前置后移参数 找到最合适的环境
    if (_pp.min_index < 0)
    {
        _pp.min_index = 0;
    }
    _pp.max_index += half_duration;
    if (_pp.max_index < 0)
    {
        _pp.max_index = 0;
    }
    return 0;
}
